package com.rslai.base.tool.servertest.command;

import com.rslai.base.tool.servertest.context.Context;
import com.rslai.base.tool.servertest.response.Response;
import com.rslai.base.tool.servertest.util.CloneUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class WaitUntilStepCommand extends CompositeStepCommand {
    private Long timeout;
    private String desc;
    private Response response;
    private static final Long INTERVAL = Long.valueOf(100L);

    public WaitUntilStepCommand(String desc, Long timeout, List<StepCommand> children) {
        super(children);
        this.timeout = timeout;
        this.desc = desc;
    }

    public Response doExecute(Response param, Context context) throws Throwable {
        long end = end();
        while (true) {
            Boolean success = executeChildren(param, context);
            if (success.booleanValue()) {
                return this.response;
            }
            if (isTimeout(end)) {
                throw new TimeoutException(String.format("超时时间已过: %s", new Object[]{this.timeout}));
            }
            waitAWhile();
        }
    }

    private void waitAWhile() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(INTERVAL.longValue());
    }

    public StepCommand doClone() {
        return new WaitUntilStepCommand(this.desc, this.timeout, CloneUtil.cloneStepCommand(this.children));
    }

    private boolean isTimeout(long end) {
        return System.currentTimeMillis() > end;
    }

    private Boolean executeChildren(Response param, Context context) {
        try {
            this.response = super.doExecute(param, context);
            return Boolean.TRUE;
        } catch (Throwable e) {
        }
        return Boolean.FALSE;
    }

    private long end() {
        return System.currentTimeMillis() + this.timeout.longValue();
    }

    public Map<String, Object> toReport() {
        Map details = new HashMap();
        details.put("stepName", String.format("等待子命令执行完毕或超时:%s", new Object[]{this.desc}));
        details.put("name", String.valueOf(this.timeout) + "ms");
        List params = new ArrayList();
        details.put("params", params);
        return details;
    }
}
